#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QSerialPortInfo>
#include <QThread>
#include <QTimer>
#include <QRandomGenerator>
#include <algorithm> // 用于std::max
#include <cmath>     // 用于std::ceil

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置窗口标题
    setFixedSize(960, 600);
    setWindowTitle("功率监视上位机");

    //创建定时器对象
    timer = new QTimer(this);

    //构造函数里，堆里创建一个对象
    serialPort = new QSerialPort(this);

    //定时器连接函数
    connect(timer, &QTimer::timeout, this, &Widget::getPowerData);



    //刷新串口
    this->on_updateSerialBt_clicked();

    creatChart();
}

double calculateAverageInRange(QLineSeries *series, int start, int end)
{
    if (!series || start > end) return 0.0;

    double sum = 0.0;
    int count = 0;

    // 遍历系列中的所有点
    for (int i = 0; i < series->count(); ++i) {
        QPointF point = series->at(i);
        // 检查点的x值是否在指定范围内
        if (point.x() >= start && point.x() <= end) {
            sum += point.y();
            count++;
        }
    }

    // 计算平均值
    return count > 0 ? sum / count : 0.0;
}

//导出功率数据
void Widget::exportPowerData()
{
    // 检查数据是否存在
    if (ch1PowerSeries->count() == 0 && ch2PowerSeries->count() == 0 && ch3PowerSeries->count() == 0)
    {
        QMessageBox::information(this, "提示", "没有数据可保存！");
        return;
    }

    // 选择保存路径
    QString filePath = QFileDialog::getSaveFileName(
        this, "保存数据", "", "CSV文件 (*.csv);;所有文件 (*)"
        );

    if (filePath.isEmpty()) return;

    // 确保文件后缀为.csv
    if (!filePath.endsWith(".csv", Qt::CaseInsensitive)) {
        filePath += ".csv";
    }

    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "错误", "无法打开文件写入！");
        return;
    }

    QTextStream out(&file);

    // 写入CSV标题行
    out << "CH1, , ,CH2, , ,CH3,,\n";
    out << "time/S,power/W, ,time/S,power/W, ,time/S,power/W\n";

    // 确定最大数据点数量，确保所有数据都能被保存
    int maxCount = std::max({ch1PowerSeries->count(),
                             ch2PowerSeries->count(),
                             ch3PowerSeries->count()});

    // 写入数据
    for (int i = 0; i < maxCount; ++i) {
        // 处理通道1数据
        if (i < ch1PowerSeries->count())
        {
            QPointF point = ch1PowerSeries->at(i);
            out << point.x() << "," << point.y();
        }
        else
        {
            out << ","; // 数据点不足时留空
        }

        // 添加分隔列
        out << ",,";

        // 处理通道2数据
        if (i < ch2PowerSeries->count())
        {
            QPointF point = ch2PowerSeries->at(i);
            out << point.x() << "," << point.y();
        }
        else
        {
            out << ",";
        }

        // 添加分隔列
        out << ",,";

        // 处理通道3数据
        if (i < ch3PowerSeries->count())
        {
            QPointF point = ch3PowerSeries->at(i);
            out << point.x() << "," << point.y();
        }
        else
        {
            out << ",";
        }

        out << "\n";
    }

    file.close();
    QMessageBox::information(this, "成功", QString("数据已保存至:\n%1").arg(filePath));
}

Widget::~Widget()
{
    delete ui;
}

//查询输出功率
void Widget::getPowerData()
{
    if(this->iGetPowerStep == 0)//发送查询报文
    {
        sendBySerialPort("MEASURE:POWER:ALL?\n");
        this->iGetPowerStep = 1;
    }
    else if(this->iGetPowerStep == 1)//处理接收报文
    {
        handlePowerData();
        this->iGetPowerStep = 0;

        //测试时间
        if(iKeepTestTime < iSetTestTime)
        {
            iKeepTestTime += 2;
            ui->testKeepTimeLCD->display(iKeepTestTime);
        }
        else//超时，结束测试
        {
            on_stopTestBt_clicked();
        }
    }
}

// 获取三个浮点数的最大值并向上取整
double getMaxAndCeil(float a, float b, float c)
{
    // 1. 获取三个数中的最大值
    float maxVal = std::max({a, b, c});

    // 2. 向上取整（返回double类型，如需int可强制转换）
    return std::ceil(maxVal);
}

//解析串口数据，获取功率数值
void Widget::handlePowerData()
{
    QByteArray dataRecv = serialPort->readAll();

    if (dataRecv.isEmpty())
    {
        return;
    }

    //去除空格
    QString dataStr = QString(dataRecv).remove(" ");

     //displayData = QString::fromUtf8(data);

    // 使用逗号分割字符串
    QStringList dataList = dataStr.split(",");

    // 检查分割结果是否符合预期，然后转换并赋值
    if (dataList.size() == 3)
    {
        fCH1RealtimeVal = dataList[0].toFloat();
        fCH2RealtimeVal = dataList[1].toFloat();
        fCH3RealtimeVal = dataList[2].toFloat();

    } else
    {
        // 处理格式错误的情况
        qWarning("数据格式不正确，无法解析");
        return;
    }

    // 追加到接收区
    ui->portTextEdit->insertPlainText("接收："+dataStr+"\n");

    // 自动滚屏
    ui->portTextEdit->moveCursor(QTextCursor::End);

    //计算最大值
    if(fCH1RealtimeVal>=fCH1MaxVal)
    {
        fCH1MaxVal = fCH1RealtimeVal;
        ui->ch1MaxValueEdit->setText(QString::number(fCH1MaxVal, 'f', 2));
    }

    if(fCH2RealtimeVal>=fCH2MaxVal)
    {
        fCH2MaxVal = fCH2RealtimeVal;
        ui->ch2MaxValueEdit->setText(QString::number(fCH2MaxVal, 'f', 2));
    }

    if(fCH3RealtimeVal>=fCH3MaxVal)
    {
        fCH3MaxVal = fCH3RealtimeVal;
        ui->ch3MaxValueEdit->setText(QString::number(fCH3MaxVal, 'f', 2));
    }

    //显示实时值
    ui->ch1RealTimeValueEdit->setText(QString::number(fCH1RealtimeVal, 'f', 2));
    ui->ch2RealTimeValueEdit->setText(QString::number(fCH2RealtimeVal, 'f', 2));
    ui->ch3RealTimeValueEdit->setText(QString::number(fCH3RealtimeVal, 'f', 2));

    //图表显示
    ch1PowerSeries->append(iKeepTestTime, fCH1RealtimeVal);//增加折线数据点
    ch2PowerSeries->append(iKeepTestTime, fCH2RealtimeVal);
    ch3PowerSeries->append(iKeepTestTime, fCH3RealtimeVal);

    axisY->setRange(0, getMaxAndCeil(fCH1MaxVal, fCH2MaxVal, fCH3MaxVal)); // 设置Y轴范围

}

//刷新串口
void Widget::on_updateSerialBt_clicked()
{
    QStringList serialNamePort;

    //清空串口号
    ui->serialNumCb->clear();

    //自动搜索当前可用串口信息
    foreach(const QSerialPortInfo &inf0, QSerialPortInfo::availablePorts())
    {
        serialNamePort<<inf0.portName();
    }
    //添加串口号
    ui->serialNumCb->addItems(serialNamePort);
}


//打开串口
void Widget::on_openSerialBt_clicked()
{
    //串口参数变量
    //初始化端口号、波特率、数据位、停止位、校验位
    serialPort->setPortName(ui->serialNumCb->currentText());
    serialPort->setBaudRate(QSerialPort::Baud9600);//波特率9600
    serialPort->setDataBits(QSerialPort::Data8);//数据位固定为8
    serialPort->setStopBits(QSerialPort::OneStop);//停止位固定为1
    serialPort->setParity(QSerialPort::NoParity);//无校验

    if(serialPort->open(QIODevice::ReadWrite) == true)
    {
        //修改按键颜色-绿
        ui->openSerialBt->setStyleSheet("background-color:green");
        QMessageBox::information(this,"提示","打开串口成功");
    }
    else
    {
        //修改按键颜色-绿
        ui->openSerialBt->setStyleSheet("background-color:red");
        QMessageBox::information(this,"提示","打开串口失败");
    }
}

//关闭串口
void Widget::on_closeSerialBt_clicked()
{
    //修改“打开串口”颜色-白
    ui->openSerialBt->setStyleSheet("background-color:white");
    serialPort->close();
}

//清空文本内容
void Widget::on_clearPortTextBt_clicked()
{
    ui->portTextEdit->clear();
}

void Widget::initPowerValue()
{

    //步骤
    iGetPowerStep = 0;

    //计时数据
    iSetTestTime =ui->setTestTimeCb->value();
    iKeepTestTime = 0;

    fCH1RealtimeVal = 0;//实时值
    fCH1MaxVal = 0;//最大值
    fCH2RealtimeVal = 0;
    fCH2MaxVal = 0;
    fCH3RealtimeVal = 0;
    fCH3MaxVal = 0;
}

void Widget::initChart()
{
    ch1PowerSeries->clear();//清除折线

    ch2PowerSeries->clear();

    ch3PowerSeries->clear();

    axisX->setRange(0, iSetTestTime);  // 设置横轴范围
}

//开始测试
void Widget::on_startTestBt_clicked()
{
    //1、弹窗提示，设置好电压电流
    QMessageBox::information(this,"提示","手动设置电压、电流!\n\n点击ok，测试开始!");

    //2、开启输出
    sendBySerialPort("SYSTEM:BEEPER\n");//蜂鸣
    QThread::msleep(10);
    sendBySerialPort("SYSTEM:REMOTE\n");//远程控制
    QThread::msleep(10);
    sendBySerialPort("OUTPUT ON\n");//开启输出
    QThread::msleep(10);
    sendBySerialPort("SYSTEM:LOCAL\n");//面板控制

    //3、初始化数据、图表
    initPowerValue();

    initChart();

    //4、开启定时器
    timer->start(1000);//1000ms

}

//发送报文 并显示到对话框
void Widget::sendBySerialPort(const char *sendData)
{
    //调整格式，发送
    serialPort->write(sendData);

    //显示在文本框
    ui->portTextEdit->insertPlainText("发送："+(QString)sendData+"\n");

    // 自动滚屏
    ui->portTextEdit->moveCursor(QTextCursor::End);
}

//结束测试
void Widget::on_stopTestBt_clicked()
{
    timer->stop();

    //功率数值归零
    fCH1RealtimeVal = 0;
    fCH1MaxVal = 0;
    fCH2RealtimeVal = 0;
    fCH2MaxVal = 0;
    fCH3RealtimeVal = 0;
    fCH3MaxVal = 0;

    sendBySerialPort("SYSTEM:BEEPER\n");//蜂鸣
    QThread::msleep(10);
    sendBySerialPort("SYSTEM:REMOTE\n");//远程控制
    QThread::msleep(10);
    sendBySerialPort("OUTPUT OFF\n");//关闭输出
    QThread::msleep(10);
    sendBySerialPort("SYSTEM:LOCAL\n");//面板控制
}

void Widget::creatChart()
{
    // 创建折线
    ch1PowerSeries = new QLineSeries();
    ch1PowerSeries->setName("CH1");
    ch1PowerSeries->setPen(QPen(Qt::red, 2));
    ch1PowerSeries->setPointsVisible(true);     // 显示数据点
    ch1PowerSeries->setMarkerSize(2);           // 圆点大小（像素）

    ch2PowerSeries = new QLineSeries();
    ch2PowerSeries->setName("CH2");
    ch2PowerSeries->setPen(QPen(Qt::green, 2));
    ch2PowerSeries->setPointsVisible(true);     // 显示数据点
    ch2PowerSeries->setMarkerSize(2);           // 圆点大小（像素）

    ch3PowerSeries = new QLineSeries();
    ch3PowerSeries->setName("CH3");
    ch3PowerSeries->setPen(QPen(Qt::blue, 2));
    ch3PowerSeries->setPointsVisible(true);     // 显示数据点
    ch3PowerSeries->setMarkerSize(2);           // 圆点大小（像素）

    //创建图表
    powerChart = new QChart();
    powerChart->addSeries(ch1PowerSeries);
    powerChart->addSeries(ch2PowerSeries);
    powerChart->addSeries(ch3PowerSeries);

    //powerChart->setTitle("电源输出功率监视");

    // 设置坐标轴
    // 初始化X轴（时间）
    axisX = new QValueAxis();
    axisX->setTitleText("时间/S");
    //axisX->setRange(0, 100);  // 初始显示10个数据点的范围
    axisX->setLabelFormat("%d");

    // 初始化Y轴（功率）
    axisY = new QValueAxis();
    axisY->setTitleText("功率/W");
    //axisY->setRange(0, 100); // 设置Y轴范围
    axisY->setLabelFormat("%.2f");

    axisX->setTickCount(11);  // X轴将显示11个刻度，10条网格线
    axisY->setTickCount(11);  // Y轴将显示11个刻度，10条网格线

    // 将坐标轴添加到图表
    powerChart->addAxis(axisX, Qt::AlignBottom);
    powerChart->addAxis(axisY, Qt::AlignLeft);

    // 缩小图表四周空白区域
    powerChart->setMargins(QMargins(5, 5, 5, 5)); // 图表边缘与内容的边距（上、右、下、左）

    // 将折线关联到坐标轴
    ch1PowerSeries->attachAxis(axisX);
    ch1PowerSeries->attachAxis(axisY);

    ch2PowerSeries->attachAxis(axisX);
    ch2PowerSeries->attachAxis(axisY);

    ch3PowerSeries->attachAxis(axisX);
    ch3PowerSeries->attachAxis(axisY);

    // 创建图表视图并设置属性
    powerChartView = new QChartView(powerChart);
    powerChartView->setRenderHint(QPainter::Antialiasing);  // 抗锯齿
    powerChartView->setGeometry(0, 0, 810, 370);  // 设置位置和大小

    powerChartView->setParent(this);

    //保存数据按钮
    QPushButton *exportDataBt = new QPushButton("导出数据", this);
    exportDataBt->setGeometry(700, 20, 64, 24); // x=20, y=100, 宽度90, 高度30
    connect(exportDataBt, &QPushButton::clicked, this, &Widget::exportPowerData);

    //求平均值按钮
    connect(ui->ch1CalculateAvgBt, &QPushButton::clicked, this, &Widget::ch1GetAvgPowerVal);
    connect(ui->ch2CalculateAvgBt, &QPushButton::clicked, this, &Widget::ch2GetAvgPowerVal);
    connect(ui->ch3CalculateAvgBt, &QPushButton::clicked, this, &Widget::ch3GetAvgPowerVal);

}

void Widget::ch1GetAvgPowerVal()
{
    int start = ui->ch1AvgValStartCb->value();
    int end   = ui->ch1AvgValEndCb->value();
    float AvgVal = calculateAverageInRange(ch1PowerSeries,start,end);
    ui->ch1AvgValueEdit->setText(QString::number(AvgVal, 'f', 2));
}

void Widget::ch2GetAvgPowerVal()
{
    int start = ui->ch2AvgValStartCb->value();
    int end   = ui->ch2AvgValEndCb->value();
    float AvgVal = calculateAverageInRange(ch2PowerSeries,start,end);
    ui->ch2AvgValueEdit->setText(QString::number(AvgVal, 'f', 2));
}

void Widget::ch3GetAvgPowerVal()
{
    int start = ui->ch3AvgValStartCb->value();
    int end   = ui->ch3AvgValEndCb->value();
    float AvgVal = calculateAverageInRange(ch3PowerSeries,start,end);
    ui->ch3AvgValueEdit->setText(QString::number(AvgVal, 'f', 2));
}



